﻿using System;
using System.Collections.Generic;


namespace RNA_Libraries
{
  public class DeleteMutation : IEquatable<DeleteMutation>, IMutation
  {
    public DeleteMutation(int position)
    {
      Position = position;
      Reads = new List<Vertex>();
    }

    #region Implementation of IMutation

    public int Position { get; private set; }

    public List<Vertex> Reads { get; private set; }

    public MutationType MutationType
    {
      get { return MutationType.Delete; }
    }

    public double Rait { get; set; }

    #endregion

    #region Implementation of IEquatable<DeleteMutation>

    public override bool Equals(object obj)
    {
      if (ReferenceEquals(null, obj)) return false;
      if (ReferenceEquals(this, obj)) return true;
      if (obj.GetType() != typeof(DeleteMutation)) return false;
      return Equals((DeleteMutation)obj);
    }

    public bool Equals(DeleteMutation other)
    {
      if (ReferenceEquals(null, other)) return false;
      if (ReferenceEquals(this, other)) return true;
      return other.Position == Position && Equals(other.MutationType, MutationType);
    }

    public override int GetHashCode()
    {
      unchecked
      {
        int result = Position;
        result = (result * 397) ^ MutationType.GetHashCode();
        return result;
      }
    }

    public static bool operator ==(DeleteMutation left, DeleteMutation right)
    {
      return Equals(left, right);
    }

    public static bool operator !=(DeleteMutation left, DeleteMutation right)
    {
      return !Equals(left, right);
    }

    #endregion
  }

  public class IdentMutation : IEquatable<IdentMutation>, IMutation
  {
    public IdentMutation(int position)
    {
      Position = position;
      Reads = new List<Vertex>();
    }
    #region Implementation of IMutation

    public int Position { get; private set; }
    public List<Vertex> Reads { get; private set; }
    public MutationType MutationType
    {
      get { return MutationType.Ident; }
    }

    public double Rait { get; set; }

    #endregion

    #region Implementation of IEquatable<IdentMutation>

    public override bool Equals(object obj)
    {
      if (ReferenceEquals(null, obj)) return false;
      if (ReferenceEquals(this, obj)) return true;
      if (obj.GetType() != typeof(IdentMutation)) return false;
      return Equals((IdentMutation)obj);
    }

    public bool Equals(IdentMutation other)
    {
      if (ReferenceEquals(null, other)) return false;
      if (ReferenceEquals(this, other)) return true;
      return other.Position == Position && Equals(other.MutationType, MutationType);
    }

    public override int GetHashCode()
    {
      unchecked
      {
        int result = Position;
        result = (result * 397) ^ MutationType.GetHashCode();
        return result;
      }
    }

    public static bool operator ==(IdentMutation left, IdentMutation right)
    {
      return Equals(left, right);
    }

    public static bool operator !=(IdentMutation left, IdentMutation right)
    {
      return !Equals(left, right);
    }

    #endregion
  }

  public class InsertMutation : IEquatable<InsertMutation>, IMutation
  {
    public InsertMutation(int position, string mut)
    {
      Position = position;
      Reads = new List<Vertex>();
      Symbol = mut;
    }

    #region Implementation of IMutation

    public int Position { get; private set; }
    public List<Vertex> Reads { get; private set; }
    public MutationType MutationType { get { return MutationType.Insert; } }

    public double Rait { get; set; }

    #endregion

    public string Symbol { get; private set; }

    #region Implementation of IEquatable<InsertMutation>

    public override bool Equals(object obj)
    {
      if (ReferenceEquals(null, obj)) return false;
      if (ReferenceEquals(this, obj)) return true;
      if (obj.GetType() != typeof(InsertMutation)) return false;
      return Equals((InsertMutation)obj);
    }

    public bool Equals(InsertMutation other)
    {
      if (ReferenceEquals(null, other)) return false;
      if (ReferenceEquals(this, other)) return true;
      return other.Position == Position && Equals(other.MutationType, MutationType) && other.Symbol == Symbol;
    }

    public override int GetHashCode()
    {
      unchecked
      {
        int result = Position;
        result = (result * 397) ^ MutationType.GetHashCode();
        result = (result * 397) ^ Symbol.GetHashCode();
        return result;
      }
    }

    public static bool operator ==(InsertMutation left, InsertMutation right)
    {
      return Equals(left, right);
    }

    public static bool operator !=(InsertMutation left, InsertMutation right)
    {
      return !Equals(left, right);
    }

    #endregion
  }

  public class ReplaceMutation : IEquatable<ReplaceMutation>, IMutation
  {
    public ReplaceMutation(int pos, string mut)
    {
      Position = pos;
      Symbol = mut;
      Reads = new List<Vertex>();
    }

    #region Implementation of IMutation

    public int Position { get; private set; }

    public MutationType MutationType { get { return MutationType.Replace; } }

    public double Rait { get; set; }

    public List<Vertex> Reads { get; private set; }

    #endregion

    public string Symbol { get; private set; }

    #region Implementation of IEquatable<ReplaceMutation>

    public override bool Equals(object obj)
    {
      if (ReferenceEquals(null, obj)) return false;
      if (ReferenceEquals(this, obj)) return true;
      if (obj.GetType() != typeof(ReplaceMutation)) return false;
      return Equals((ReplaceMutation)obj);
    }

    public bool Equals(ReplaceMutation other)
    {
      if (ReferenceEquals(null, other)) return false;
      if (ReferenceEquals(this, other)) return true;
      return other.Position == Position && Equals(other.MutationType, MutationType) && other.Symbol == Symbol;
    }

    public override int GetHashCode()
    {
      unchecked
      {
        int result = Position;
        result = (result * 397) ^ MutationType.GetHashCode();
        result = (result * 397) ^ Symbol.GetHashCode();
        return result;
      }
    }

    public static bool operator ==(ReplaceMutation left, ReplaceMutation right)
    {
      return Equals(left, right);
    }

    public static bool operator !=(ReplaceMutation left, ReplaceMutation right)
    {
      return !Equals(left, right);
    }

    #endregion
  }
  public abstract class BaseMutation<T> : IMutation, IEquatable<T>
  {
    #region Implementation of IEquatable<T>

    public abstract bool Equals(T other);

    #endregion

    #region Implementation of IMutation

    public abstract int Position { get; }
    public abstract List<Vertex> Reads { get; }
    public abstract MutationType MutationType { get; }
    public abstract double Rait { get; set; }

    #endregion
  } 

  public interface IMutation
  {
    int Position { get; }
    List<Vertex> Reads { get; }
    MutationType MutationType { get; }
    double Rait { get; set; }
  }
  public enum MutationType
  {
    Insert,
    Delete,
    Replace,
    Ident
  }


}
